package com.heima.comment.service.impl;

import com.heima.aliyun.GreenTextScan;
import com.heima.comment.service.CommentHotService;
import com.heima.comment.service.CommentService;
import com.heima.common.exception.CustException;
import com.heima.feigns.UserFeign;
import com.heima.model.article.pojos.ApUser;
import com.heima.model.comment.dtos.CommentDTO;
import com.heima.model.comment.dtos.CommentLikeDTO;
import com.heima.model.comment.dtos.CommentSaveDTO;
import com.heima.model.comment.pojos.ApComment;
import com.heima.model.comment.pojos.ApCommentLike;
import com.heima.model.comment.vos.ApCommentVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.treadlocal.AppThreadLocalUtils;
import org.apache.commons.collections.CollectionUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class CommentServiceImpl implements CommentService {
    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private UserFeign userFeign;

    @Override
    public ResponseResult publishComment(CommentSaveDTO dto) {

        //阿里云文本审核
        handleText(dto.getContent());


        //是否登录，获取登录信息
        ApUser apUser = AppThreadLocalUtils.getUser();
        //用户为空就直接抛异常
        if (apUser == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN, "用户未登录");
        }

        //远程调用feign擦汗寻用户信息
        ResponseResult<ApUser> apUserfeign = userFeign.findUserById(apUser.getId());

        if (apUserfeign.getData() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE, "远程调用失败了");
        }
        //将远程查询到的信息 ， 现状到 apuser
        apUser = apUserfeign.getData();

        //创建一个apComment实体类
        ApComment apComment = new ApComment();

        //将用户信息set进去

        apComment.setAuthorId(apUser.getId());

        apComment.setAuthorName(apUser.getName());

        apComment.setCreatedTime(new Date());

        apComment.setUpdatedTime(new Date());

        apComment.setContent(dto.getContent());

        apComment.setImage(apUser.getImage());

        apComment.setArticleId(dto.getArticleId());

        apComment.setLikes(0);
        apComment.setReply(0);

        apComment.setType((short) 0);
        apComment.setFlag((short) 0);

        //用mongo的保存方法
        mongoTemplate.save(apComment);

        return ResponseResult.okResult();
    }


    //查询评论列表
    @Override
    public ResponseResult findCommentList(CommentDTO dto) {
        //1 参数检查
        // 页大小
        Integer size = dto.getSize();
        if (size == null || size <= 0) {
            size = 10;
        }
        dto.setSize(size);

        //   ========================需要变更处 start =============================
        //2 查询Mongo文章所有评论列表
        List<ApComment> apComments = null;
        if (dto.getIndex().intValue() == 1) { // 判断当前是否是第一页评论
            // 先查询热点评论集合  （最多5条） (条件: flag=1, 文章id, 点赞降序)
            Query query = Query.query(Criteria.where("articleId").is(dto.getArticleId()).and("flag").is(1)).with(Sort.by(Sort.Direction.DESC, "likes"));
            apComments = mongoTemplate.find(query, ApComment.class);
            // 新size = size - 热评数量
            // 查询第一页剩余普通评论 (条件: 文章id, flag=0, 时间降序, limit:新size)
            // 合并 热点评论  普通评论   热点list.addAll(普通list)
            //热点集合不为空
            if (CollectionUtils.isNotEmpty(apComments)) {
                size = size - apComments.size();
                Query query1 = Query.query(Criteria.where("articleId").is(dto.getArticleId())
                        .and("flag").is(0).and("createdTime").lt(dto.getMinDate()))
                        .limit(size).with(Sort.by(Sort.Direction.DESC, "createdTime"));

                List<ApComment> normalComments = mongoTemplate.find(query1, ApComment.class);

                apComments.addAll(normalComments);

            } else {
                // 不是第一页直接查询普通评论
                apComments = mongoTemplate.find(
                        Query.query(Criteria.where("articleId").is(dto.getArticleId())
                                .and("flag").is(0).and("createdTime").lt(dto.getMinDate()))
                                .limit(size).with(Sort.by(Sort.Direction.DESC, "createdTime"))
                        , ApComment.class);
            }
            }else {
            apComments = mongoTemplate.find(
                    Query.query(Criteria.where("articleId").is(dto.getArticleId())
                            .and("flag").is(0).and("createdTime").lt(dto.getMinDate()))
                            .limit(size).with(Sort.by(Sort.Direction.DESC, "createdTime"))
                    , ApComment.class);
        }
            // ========================需要变更处 end =============================


            //如果没有登陆 ， 就直接返回， 给没有登陆的设备用户返回可以看到评论
            ApUser user = AppThreadLocalUtils.getUser();
            if (user == null) {
                return ResponseResult.okResult(apComments);
            }

            //如果登录了 ，需要检查这些评论中有那些人点赞过
            List<String> ids = apComments.stream().map(o -> o.getId()).collect(Collectors.toList());

            List<ApCommentLike> apCommentLikes = mongoTemplate.find(Query.query(Criteria.where("authorId").is(user.getId())
                    .and("commentId").in(ids)), ApCommentLike.class);

            List<ApCommentVo> apCommentVoList = new ArrayList<>();

            if (apComments != null && apCommentLikes != null) {
                for (ApComment comment : apComments) {
                    ApCommentVo apCommentVo = new ApCommentVo();
                    BeanUtils.copyProperties(comment, apCommentVo);

                    for (ApCommentLike commentLike : apCommentLikes) {
                        if (commentLike.getId().equals(comment.getId())) {
                            apCommentVo.setOperation((short) 0);
                        }
                    }
                    apCommentVoList.add(apCommentVo);
                }
                return ResponseResult.okResult(apCommentVoList);
            }
        return ResponseResult.okResult(apComments);
    }

    //点赞




    @Autowired
    RedissonClient redissonClient;

    @Autowired
    CommentHotService commentHotService;


    @Override
    public ResponseResult likeComment(CommentLikeDTO dto) {

        ApUser user = AppThreadLocalUtils.getUser();
        if (user == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN, "用户需要登录");
        }

//枷锁
        RLock lock = redissonClient.getLock("like-lock");

        lock.lock();


        ApComment apComment;
        try {
            apComment = mongoTemplate.findById(dto.getCommentId(), ApComment.class);
            if (apComment == null) {
                return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
            }


            ApCommentLike apCommentLike = mongoTemplate.findOne(
                    Query.query(Criteria.where("authorId").is(user.getId())
                            .and("commentId").is(dto.getCommentId())
                    ),
                    ApCommentLike.class);


//        if (apCommentLike != null && dto.getOperation().intValue() == 0) {
//            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_EXIST, "禁止重复点赞");
//        }


            if (dto.getOperation().intValue() == 0) {
                apComment.setLikes(apComment.getLikes() + 1);
                mongoTemplate.save(apComment);

                //引用热点方法,再不是热点文章的时候,如果自身的点赞大于10 ,  就调用热评方法
                if (apComment.getLikes() >= 10
                        && apComment.getFlag().shortValue() == 0) {
                    commentHotService.hotCommentExecutor(apComment);
                }


                apCommentLike = new ApCommentLike();
                apCommentLike.setAuthorId(user.getId());
                apCommentLike.setCommentId(apComment.getId());
                apCommentLike.setOperation(dto.getOperation());
                mongoTemplate.save(apCommentLike);


                //删除点赞信息
            } else {
                if ((apComment.getLikes() - 1) < 0) {
                    ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_ALLOW, "取消点赞不能为负数");
                }
                apComment.setLikes(apComment.getLikes() - 1);
                mongoTemplate.save(apComment);

                //删除关联信息
                mongoTemplate.remove(Query.query(Criteria.
                        where("authorId").is(user.getId())
                        .and("commentId").is(apComment.getId())), ApCommentLike.class);
            }
        } finally {
            lock.unlock();
        }

        Map<String, Object> resultMap = new HashMap<>();

        resultMap.put("likes", apComment.getLikes());

        return ResponseResult.okResult(resultMap);
    }





    //阿里云的检查方法
    @Autowired
    GreenTextScan greenTextScan;

    private void handleText(String content) {

        try {
            Map map = greenTextScan.greenTextScan(content);
            //有返回结果
            String suggestion = (String) map.get("suggestion");

            switch (suggestion) {
                case "review":
                    CustException.cust(AppHttpCodeEnum.DATA_NOT_ALLOW, "文本中有违规内容，审核失败");
                    break;
                case "block":
                    CustException.cust(AppHttpCodeEnum.DATA_NOT_ALLOW, "文本中有违规内容，审核失败");
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
            CustException.cust(AppHttpCodeEnum.DATA_NOT_ALLOW, "文本中有违规内容，审核失败");
        }
    }
}
